package fr.vod.threads;

import java.net.DatagramPacket;
import java.net.InetAddress;

import android.app.IntentService;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiManager.MulticastLock;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.util.Log;
import fr.vod.demo.videoshareUcp.R;
import fr.vod.net.Receiver;
import fr.vod.net.ReceiverMulticast;
import fr.vod.net.Sender;
import fr.vod.net.SenderMulticast;
import fr.vod.util.LogHelper;
import fr.vod.videoShareUcp.MainActivity;

public class ServiceMulticastVideo extends IntentService {

	private int port=1234;
	
	// / tag des logs
	private final static String logTag = ServiceMulticastVideo.class.getName();
	
	// / Instance "attrapant" les messages entrant
	Messenger messenger = new Messenger(new IncomingHandler());
	public Messenger activityMessenger;
	
	//Statistiques reseau
	//private NetworkWatcher networkWatcher;
	
	// / indique le type du message
	static public final int MESSAGE_TYPE = 1;
	public static final int MESSAGE_CMD = 2;
	public static final int MESSAGE_STAT = 3;
	public static final int MESSAGE_START_LISTNENING = 3;
	
	private boolean isBinded = false;
	
	private Receiver receiver;
	private Sender sender;
	
    public ServiceMulticastVideo() { 	
		super("ServiceMultiCast");
		

    }
    
	@Override
	public IBinder onBind(Intent intent) {
		LogHelper.entree(logTag, "onBind");
		MainActivity.networkWatcher.startWatching();
		IBinder bind = messenger.getBinder();
		isBinded = true;
		
		return bind;
	}

	@Override
	public void onConfigurationChanged(Configuration newConfig) {
		LogHelper.entree(logTag, "onConfigurationChanged");
		super.onConfigurationChanged(newConfig);

	}
	@Override
	public void onRebind(Intent intent) {
		LogHelper.entree(logTag, "onRebind");
		super.onRebind(intent);
	}	
	
	@Override
    protected void onHandleIntent(Intent workIntent) {
		// Gets data from the incoming Intent
        //String dataString = workIntent.getDataString();
		LogHelper.entree(logTag, "OnHandleIntent");
		initiateServiceSockets();
		DatagramPacket packet = null;
		String myAddress = getLocalIpAddress();
		
		while (isBinded) {
			try {
				packet = receiver.receivePacket();
				MainActivity.networkWatcher.addReceivedBytes(packet.getLength(), System.currentTimeMillis());
				//sendStatsToActivity();
				if (packet.getAddress().getHostAddress().contains(myAddress))
					continue;
				
				LogHelper.information(logTag, "Packet received from " + packet.getAddress().getHostAddress());
				
				String msg = new String(packet.getData()).trim();
				Log.i("blu", "On parse : '" + msg + "'");
				messageParser(msg);
				
			} catch (Exception e) {
				e.printStackTrace();
			}	
		}
    }
	
	public void initiateServiceSockets() {
		String ip = getString(R.string.ip_synchro);
		Log.i("blu", "Connecting to " + ip);
		try {
			WifiManager wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);
			MulticastLock mLock = wifi.createMulticastLock("mylock");
			mLock.acquire();
			receiver = new ReceiverMulticast(InetAddress.getByName(ip),
					port);
			receiver.startWatching();
			
			sender = new SenderMulticast(InetAddress.getByName(ip), port);
			sender.startWatching();
		}
		catch (Exception e ){
			e.printStackTrace();
		}
		
	}	

	protected void messageParser(String message) {
		
		if (message.contains("PLAY")) {
			Log.i("Message Parser", "PLAY");
			sendMessageToActivity("PLAY"+ "|" +String.valueOf(message.subSequence(message.indexOf('|')+1, message.length())));
			
			
		} else if (message.contains("PAUSE")) {
			Log.i("Message Parser", "PAUSE");
			sendMessageToActivity("PAUSE"+ "|"+String.valueOf(message.subSequence(message.indexOf('|')+1, message.length())));
		}
		else if (message.contains("TIME")){
			Log.i("Message Parser", "TIME");
			sendMessageToActivity("TIME"+"|"+String.valueOf(message.subSequence(message.indexOf('|')+1, message.length())));
		}
	}
	
	
	
	private void sendMessageToActivity(String message) {
		Message msgActivity = Message.obtain(null, MESSAGE_CMD, 0, 0);
		Bundle bundleActivity = msgActivity.getData();
		
		bundleActivity.putString("CMD", message);
		LogHelper.information(logTag, "sending message to activity : " + message);
		try {
			activityMessenger.send(msgActivity);
		} catch (RemoteException e) {
			LogHelper.erreur(logTag, e.getMessage());
		}

	}
	
	/**
	 * Handler des messages entrant.
	 * 
	 * repond a l'emetteur avec le flag pour
	 * savoir si le bluetooth est active ou pas
	 * 
	 */
	class IncomingHandler extends Handler {

		@Override
		public void handleMessage(Message msg) {
			LogHelper.entree(logTag, "handleMessage");


			switch (msg.what) {
			case 	MESSAGE_TYPE:
				activityMessenger = msg.replyTo;

				Message msgActivity = Message.obtain(null, MainActivity.MESSAGE_INIT, 0, 0);
				Bundle bundleActivity = msgActivity.getData();

				bundleActivity.putString("flag", "YOOO");
				try {
					activityMessenger.send(msgActivity);
				} catch (RemoteException e) {
					LogHelper.erreur(logTag, e.getMessage());
				}
				break;
			case MESSAGE_CMD:
				LogHelper.information(logTag, msg.getData().getString("CMD"));
				LogHelper.information(logTag, String.valueOf(msg.getData().getInt("TIME")));
				sendMulticastCommand(msg.getData().getString("CMD")+"|"+String.valueOf(msg.getData().getInt("TIME"))+"|"+String.valueOf(msg.getData().getLong("TIMESTAMP")));
				break;
			default:
				super.handleMessage(msg);
			}
		}
	}

	public class SendMulticastCommandTask extends AsyncTask<String, Void, Void>{

	    @Override
	    protected Void doInBackground(String... params) {
	    	String message = params[0];
	    	LogHelper.information(logTag, "Sending " + message);
	    	try {
				sender.send(message);
				MainActivity.networkWatcher.addSentBytes(message.getBytes().length, System.currentTimeMillis());
				LogHelper.information("networkWatcher - Upload", String.valueOf(MainActivity.networkWatcher.getUploadSpeed()));
				LogHelper.information("socket - Upload", String.valueOf(sender.getUploadSpeed()));
				LogHelper.information("networkWatcher - Download", String.valueOf(MainActivity.networkWatcher.getDownloadSpeed()));
				LogHelper.information("socket - Download", String.valueOf(receiver.getDownloadSpeed()));
			} catch (Exception e) {
				e.printStackTrace();
			}
			
	    	return null;
	        
	    }
	}
	
	public void sendMulticastCommand(String string) {
		LogHelper.information(logTag, "sendMulticastCommand");
		new SendMulticastCommandTask().execute(string);
	}
	
	private String getLocalIpAddress() {
		WifiManager wifiManager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
		int myIp = wifiManager.getConnectionInfo().getIpAddress();

		int intMyIp3 = myIp / 0x1000000;
		int intMyIp3mod = myIp % 0x1000000;
		int intMyIp2 = intMyIp3mod / 0x10000;
		int intMyIp2mod = intMyIp3mod % 0x10000;
		int intMyIp1 = intMyIp2mod / 0x100;
		int intMyIp0 = intMyIp2mod % 0x100;
		String s = String.valueOf(intMyIp0) + "." + String.valueOf(intMyIp1)
				+ "." + String.valueOf(intMyIp2) + "."
				+ String.valueOf(intMyIp3);
		boolean chaineOK = true;
		for (int i = 0; i < s.length(); i++)
			if (s.charAt(i) != '.' && !Character.isDigit(s.charAt(i)))
				chaineOK = false;
		if (!chaineOK)
			s = null;

		return s;
	}


}